home *** CD-ROM | disk | FTP | other *** search
- /* GRAPHIC LISP */
- /* Scritto nel 1991-94 da Zoia Andrea Michele */
- /* Via Pergola #1 Tirano (SO) Tel. 0342-704210 */
- /* file clos_lfl.c */
-
- #include "clos.h"
-
- #define PHASE_PARAM 0
- #define PHASE_OPTIONAL 1
- #define PHASE_REST 2
- #define PHASE_REST_1 3
- #define PHASE_REST_2 4
- #define PHASE_KEY 5
- #define PHASE_AUX 6
-
-
- void lambda_eval(ufunc,param,nout,genv,lenv,ev_fl)
- node ufunc;
- node param;
- node_p *nout;
- node genv;
- node lenv;
- unsigned ev_fl;
- {
- /* valutazione di una lambda */
- /* param sono i parametri attuali della lambda gia' valutati */
-
- node ufunc_par=UFUNC_PAR(ufunc);
- node new_lenv=UFUNC_ENV(ufunc);
- node new_genv=genv;
- int phase=PHASE_PARAM;
- node parlist=param;
- node name;
- node value;
- node tmp;
-
- /* new_lenv e' il nuovo environment della lambda : e'una A-list */
- /* new_genv e' il nuovo environment di DEFVAR */
-
- for(;;){
- /* lo scopo si questo switch e' quello di assegnare alle 2 variabili */
- /* name e value il nome e il valore riferiti al parametro corrente */
- /* alla fine dello switch nome e valore verranno messi insieme */
- switch(phase){
- case PHASE_PARAM:
- if(IS_CONS(ufunc_par)){ /* ufunc_par=( n1 n2 ... nn ) */
- if(IS_CONS(parlist)){
- /* ok c'e' il parametro */
- name=CONSLEFT(ufunc_par);
- value=CONSLEFT(parlist);
- ufunc_par=CONSRIGHT(ufunc_par);
- parlist=CONSRIGHT(parlist);
- break;
- }
- /* non c'e' il parametro */
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,¶m);
- }
- ufunc_par=UFUNC_OPT(ufunc);
- phase=PHASE_OPTIONAL;
-
- case PHASE_OPTIONAL:
- if(IS_CONS(ufunc_par)){
- /* ufunc_par= ( (n1 . v1) (n2 . v2) ... (nn . vn)) */
- name=CONSLEFT(ufunc_par); /* name = (n1 . v1) */
- if(IS_CONS(parlist)){
- name=CONSLEFT(name);
- value=CONSLEFT(parlist);
- parlist=CONSRIGHT(parlist);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
- eval(CONSRIGHT(name),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- name=CONSLEFT(name);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
- ufunc_par=UFUNC_REST(ufunc);
- phase=PHASE_REST;
-
- case PHASE_REST:
- /* ufunc par e' nil o un nome */
- if(ufunc_par!=NIL){
-
- /* bisogna spezzare parlist fino a quando si trova un nodo CNAME':'*/
- /* parlist e' uguale alla lista a partire dal primo nodo : */
- /* value e' il pezzo prima di parlist */
- value=tmp=parlist;
- name=NIL;/*previous*/
- while(IS_CONS(tmp)){
- if(IS_VALUE(CONSLEFT(tmp))&&GET_VTYPE(CONSLEFT(tmp))==NT_CNAME){
- if(name!=NIL){
- CONSRIGHT(name)=NIL;
- parlist=tmp;
- }else{
- value=NIL;
- /* e parlist non si tocca */
- }
- break;
- }
- name=tmp;/*previous*/
- tmp=CONSRIGHT(tmp);
- }
- if(!IS_CONS(tmp))parlist=NIL;
- name=ufunc_par;
- ufunc_par=UFUNC_KEY(ufunc);
- phase=PHASE_KEY;
- break; /* il giro dopo si passa comunque a PHASE_KEY */
- }
- ufunc_par=UFUNC_KEY(ufunc);
- phase=PHASE_KEY;
-
- case PHASE_KEY:
- /*printf("\nPHASE KEY:parlist=");fprint_func(parlist,stdout); */
- if(IS_CONS(parlist)){
- name=CONSLEFT(parlist);
- /* name deve essere :NOME */
- if(IS_VALUE(name)&&GET_VTYPE(name)==NT_CNAME&&
- IS_NAME(CNAME(name))&&HAS_NAME(CNAME(name))){
- name=CNAME(name);
- if(IS_CONS(parlist=CONSRIGHT(parlist))){
- value=CONSLEFT(parlist);
- /* si cerca name nella ufunc-par */
- /* se lo si trova si marca ufunc-par e si assegna */
- tmp=ufunc_par;
- while(IS_CONS(tmp)){
- if(CONSLEFT(CONSLEFT(tmp))==name){
- REM(CONSLEFT(tmp));
- break;
- }
- tmp=CONSRIGHT(tmp);
- }
- /* qui' se si e' trovato name nella ufunc_par tmp e' un cons */
- /* che tra l'altro e' REM altrimenti tmp e' NIL */
- if(!IS_CONS(tmp)){
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_TOOMANYARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,&name);
- }
- parlist=CONSRIGHT(parlist);
- break; /* si assegna: name=value */
- }
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_FEWARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,¶m);
- }
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_TOOMANYARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,¶m);
- }
- /* qui' ci si arriva solo se parlist e' finita o e' vuota */
- HalfWhile:
- if(IS_CONS(ufunc_par)){
- tmp=CONSLEFT(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- if(IS_REM(tmp)){
- UNREM(tmp);
- goto HalfWhile;
- }
- name=CONSLEFT(tmp);
- eval(CONSRIGHT(tmp),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- break;
- }
- ufunc_par=UFUNC_AUX(ufunc);
- phase=PHASE_AUX;
-
- case PHASE_AUX:
- if(IS_CONS(ufunc_par)){
- name=CONSLEFT(ufunc_par);
- eval(CONSRIGHT(name),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- name=CONSLEFT(name);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
-
-
- /* valutazione delle s-espressioni della lambda */
- /* usando GlobalENVironment e NEW_LocalENVironment */
- /* il flag di valutazione e' sempre EVAL_NORM tranne per */
- /* l'ultima s-espressione che lo ha settato a ev_fl */
- /* ev_fl e' uno dei parametri passati all' inizio. */
- /* nota: UFUNC_SEX(ufunc) e' sicuramente un CONS. */
-
- /* si costruisce la lista del nuovo local-environment */
-
- ufunc_par=UFUNC_SEX(ufunc);
- /* vedere se e' il caso di ripulire i nodi che sono stati */
- /* usati per creare l'environment */
- /* NB: ufunc_par non e' mai NIL ma contiene almeno 1 cons */
- while(IS_CONS(CONSRIGHT(ufunc_par))){
- eval(CONSLEFT(ufunc_par),nout,new_genv,new_lenv,EVAL_NORM);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- eval(CONSLEFT(ufunc_par),nout,new_genv,new_lenv,ev_fl);
- return;
-
- }/* switch phase */
-
- /* fase di assegnamento del valore VALUE all' atomo NAME */
- internal_update_environment(name,value,&new_genv,&new_lenv);
- }/* for(;;) */
- }
-
-
-
- void macro_eval(ufunc,param,nout,genv,lenv,ev_fl)
- node ufunc;
- node param;
- node_p *nout;
- node genv;
- node lenv;
- unsigned ev_fl;
- {
- /* valutazione di una macro */
- /* Φ identica alla lambda solo che si crea un environment locale appendendo
- quello della lambda a quello giα esistente */
- /* in questo modo si ottiene un comportamento equivalente alla sostituzione lessicale
- della macro nel contesto ove viene usata. */
- /* param sono i parametri attuali della lambda gia' valutati */
-
-
- node ufunc_par=UFUNC_PAR(ufunc);
- node new_lenv=UFUNC_ENV(ufunc);
- node new_genv=genv;
- int phase=PHASE_PARAM;
- node parlist=param;
- node name;
- node value;
- node tmp;
- node last_ufuncenv;
-
- /* new_lenv e' il nuovo environment della lambda : e'una A-list */
- /* new_genv e' il nuovo environment di DEFVAR */
-
-
- last_ufuncenv=tmp=UFUNC_ENV(ufunc);
- while(IS_CONS(tmp)){
- last_ufuncenv=tmp;
- tmp=CONSRIGHT(tmp);
- }
- if(last_ufuncenv==NIL){
- new_lenv=lenv;
- }else{
- CONSRIGHT(last_ufuncenv)=lenv;
- new_lenv=UFUNC_ENV(ufunc);
- }
-
-
-
- for(;;){
- /* lo scopo si questo switch e' quello di assegnare alle 2 variabili */
- /* name e value il nome e il valore riferiti al parametro corrente */
- /* alla fine dello switch nome e valore verranno messi insieme */
- switch(phase){
- case PHASE_PARAM:
- if(IS_CONS(ufunc_par)){
- if(IS_CONS(parlist)){
- /* ok c'e' il parametro */
- name=CONSLEFT(ufunc_par);
- value=CONSLEFT(parlist);
- ufunc_par=CONSRIGHT(ufunc_par);
- parlist=CONSRIGHT(parlist);
- break;
- }
- /* non c'e' il parametro */
- error(E_FEWARGS,ERR_MERROR|ERR_PNODE|ERR_TBLVL,¶m);
- }
- ufunc_par=UFUNC_OPT(ufunc);
- phase=PHASE_OPTIONAL;
-
- case PHASE_OPTIONAL:
- if(IS_CONS(ufunc_par)){
- name=CONSLEFT(ufunc_par);
- if(IS_CONS(parlist)){
- name=CONSLEFT(name);
- value=CONSLEFT(parlist);
- parlist=CONSRIGHT(parlist);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
- eval(CONSRIGHT(name),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- name=CONSLEFT(name);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
- ufunc_par=UFUNC_REST(ufunc);
- phase=PHASE_REST;
-
- case PHASE_REST:
- /* ufunc par e' nil o un nome */
- if(ufunc_par!=NIL){
-
- /* bisogna spezzare parlist fino a quando si trova un nodo CNAME':'*/
- /* parlist e' uguale alla lista a partire dal primo nodo : */
- /* value e' il pezzo prima di parlist */
- value=tmp=parlist;
- name=NIL;/*previous*/
- while(IS_CONS(tmp)){
- if(IS_VALUE(CONSLEFT(tmp))&&GET_VTYPE(CONSLEFT(tmp))==NT_CNAME){
- if(name!=NIL){
- CONSRIGHT(name)=NIL;
- parlist=tmp;
- }else{
- value=NIL;
- /* e parlist non si tocca */
- }
- break;
- }
- name=tmp;/*previous*/
- tmp=CONSRIGHT(tmp);
- }
- if(!IS_CONS(tmp))parlist=NIL;
- name=ufunc_par;
- ufunc_par=UFUNC_KEY(ufunc);
- phase=PHASE_KEY;
- break; /* il giro dopo si passa comunque a PHASE_KEY */
- }
- ufunc_par=UFUNC_KEY(ufunc);
- phase=PHASE_KEY;
-
- case PHASE_KEY:
- /*printf("\nPHASE KEY:parlist=");fprint_func(parlist,stdout); */
- if(IS_CONS(parlist)){
- name=CONSLEFT(parlist);
- /* name deve essere :NOME */
- if(IS_VALUE(name)&&GET_VTYPE(name)==NT_CNAME&&
- IS_NAME(CNAME(name))&&HAS_NAME(CNAME(name))){
- name=CNAME(name);
- if(IS_CONS(parlist=CONSRIGHT(parlist))){
- value=CONSLEFT(parlist);
- /* si cerca name nella ufunc-par */
- /* se lo si trova si marca ufunc-par e si assegna */
- tmp=ufunc_par;
- while(IS_CONS(tmp)){
- if(CONSLEFT(CONSLEFT(tmp))==name){
- REM(CONSLEFT(tmp));
- break;
- }
- tmp=CONSRIGHT(tmp);
- }
- /* qui' se si e' trovato name nella ufunc_par tmp e' un cons */
- /* che tra l'altro e' REM altrimenti tmp e' NIL */
- if(!IS_CONS(tmp)){
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_TOOMANYARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,&name);
- }
- parlist=CONSRIGHT(parlist);
- break; /* si assegna: name=value */
- }
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_FEWARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,¶m);
- }
- while(IS_CONS(ufunc_par)){
- UNREM(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- error(E_TOOMANYARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,¶m);
- }
- /* qui' ci si arriva solo se parlist e' finita o e' vuota */
- HalfWhile:
- if(IS_CONS(ufunc_par)){
- tmp=CONSLEFT(ufunc_par);
- ufunc_par=CONSRIGHT(ufunc_par);
- if(IS_REM(tmp)){
- UNREM(tmp);
- goto HalfWhile;
- }
- name=CONSLEFT(tmp);
- eval(CONSRIGHT(tmp),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- break;
- }
- ufunc_par=UFUNC_AUX(ufunc);
- phase=PHASE_AUX;
-
- case PHASE_AUX:
- if(IS_CONS(ufunc_par)){
- name=CONSLEFT(ufunc_par);
- eval(CONSRIGHT(name),nout,genv,lenv,EVAL_NORM);
- value=calc_pointer(nout);
- name=CONSLEFT(name);
- ufunc_par=CONSRIGHT(ufunc_par);
- break;
- }
-
-
- /* valutazione delle s-espressioni della lambda */
- /* usando GlobalENVironment e NEW_LocalENVironment */
- /* il flag di valutazione e' sempre EVAL_NORM tranne per */
- /* l'ultima s-espressione che lo ha settato a ev_fl */
- /* ev_fl e' uno dei parametri passati all' inizio. */
- /* nota: UFUNC_SEX(ufunc) e' sicuramente un CONS. */
-
- /* si costruisce la lista del nuovo local-environment */
- /* lenv-modifica */
-
- ufunc_par=UFUNC_SEX(ufunc);
- /* vedere se e' il caso di ripulire i nodi che sono stati */
- /* usati per creare l'environment */
- /* NB: non e' mai NIL ma contiene almeno 1 cons */
- while(IS_CONS(CONSRIGHT(ufunc_par))){
- eval(CONSLEFT(ufunc_par),nout,new_genv,new_lenv,EVAL_NORM);
- ufunc_par=CONSRIGHT(ufunc_par);
- }
- eval(CONSLEFT(ufunc_par),nout,new_genv,new_lenv,ev_fl);
- /** variazione macro ***/
- if(last_ufuncenv!=NIL)CONSRIGHT(last_ufuncenv)=NIL;
- return;
-
- }/* switch phase */
-
- /* fase di assegnamento del valore VALUE all' atomo NAME */
- internal_update_environment(name,value,&new_genv,&new_lenv);
- }/* for(;;) */
- }
-
-
-
-
-